<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body style="font-size: 20px">
<pre>
  this
  在绝大多数情况下，函数的调用方式决定了this的值。
  当一个函数在其主体中使用 this 关键字时，可以通过使用函数继承自Function.prototype 的 call 或 apply 方法将 this 值绑定到调用中的特定对象。
  f.bind(someObject)会创建一个与f具有相同函数体和作用域的函数
  this值在进入上下文时确定，并且在上下文运行期间永久不变。this 被设置为他被创建时的环境
  箭头函数有几个使用注意点。函数体内的this对象，就是定义时所在的对象，而不是使用时所在的对象。
</pre>
<script>
  console.group('start')
  console.log(this === window);
  var a = 37;// a = 37
  console.log(window.a); // 37

  this.b = "MDN";
  console.log(window.b)  // "MDN"
  console.log(b)         // "MDN"
  console.groupEnd()
  console.group('start')

  var a = 100

  obj1 = {
    a: 1
  }

  function m1() {
    return this.a
  }

  console.log(m1())
  console.log(m1.call(obj1))
  console.log(m1.apply(obj1))

  function add(c, d) {
    return this.a + this.b + c + d;
  }

  let o = {a: 1, b: 3};
  //Function.prototype 的 call 或 apply 方法
  //function才有
  console.log(add.call(o, 10, 10))//多参数
  console.log(add.apply(o, [10, 20]))//数组
  console.groupEnd()
  console.group('start')

  function m2() {
    return this.a
  }

  //Function.prototype.bind
  //this将永久地被绑定到了bind的第一个参数，无论这个函数是如何被调用的。
  //函数是相同的，只是永久绑定了一个作用域
  let g = m2.bind({a: "test"});
  // let gg = g
  console.log(g())
  // g = m2.bind({a: "test1234"});
  console.log(g())
  // console.log(gg())
  let ggg = g.bind({a: "test1234"});
  console.log(ggg())

  let obj2 = {
    a: 10,
    ggg
  }
  console.log(obj2.a)
  //即使放在对象里面，还是输出bind的值
  console.log(obj2.ggg())

  console.groupEnd()
  console.group('箭头函数->this与封闭词法环境的this保持一致')

  let m3 = () => {
    return this === window
  }

  var a = 100
  console.log(m3())
  let obj3 = {
    a: 10,
    m1: () => {
      console.log(this.a)//获得了全局的a 100 是在window定义的
    },
    m2: function () {
      console.log(this.a)//获取对象内部的 10
    },
    m3: function () {
      return (() => this.a);
    }
  }
  obj3.m1()
  obj3.m2()
  console.log(obj3.m3())
  console.groupEnd()
</script>
</body>
</html>
